package com.jiusem.cordova.wechatpay;

import java.io.StringReader;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;

import net.sourceforge.simcpux.Constants;
import net.sourceforge.simcpux.MD5;
import net.sourceforge.simcpux.Util;

import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaPlugin;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONArray;
import org.json.JSONObject;
import org.xmlpull.v1.XmlPullParser;

import com.tencent.mm.sdk.modelpay.PayReq;
import com.tencent.mm.sdk.openapi.IWXAPI;
import com.tencent.mm.sdk.openapi.WXAPIFactory;

import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;
import android.util.Xml;
import android.widget.Toast;

public class WechatPay extends CordovaPlugin{
	
	private static final String TAG = "MicroMsg.SDKSample.PayActivity";
	private static WechatPay instance;
	PayReq req;
	IWXAPI msgApi;
	StringBuffer sb;
	String prepayId;
	JSONArray args;
	protected static CallbackContext cordovaContext;
	
	public WechatPay(){
		instance = this; 
	}

	public boolean execute(String action , JSONArray args, CallbackContext callbackContext ){
		
		if(action.equals("test")){
			this.test();
		}else if(action.equals("register")){
			this.register();
		}else if(action.equals("getPrepayId")){
			this.getPrepayId();
		}else if(action.equals("genPayReq")){
			this.genPayReq();
		}else if(action.equals("sendPayReq")){
			this.sendPayReq();
		}else if(action.equals("pay")){
			this.args = args;
			WechatPay.cordovaContext = callbackContext;
			this.pay();
		}
		
		return true;
	}
	
	public void pay(){
		this.toast("请稍后...");
		//注册
		this.register();
		this.getPrepayId();
	}

	//向微信注册
	public void register(){
		msgApi = WXAPIFactory.createWXAPI(this.cordova.getActivity(), null);
		boolean result = msgApi.registerApp(Constants.APP_ID);
		if(result){
			//this.toast("register success");
		}else{
			this.toast("注册失败");
		}
	}
	
	//获取PrepayId
	public void getPrepayId(){
		
		GetPrepayIdTask getPrepayId = new GetPrepayIdTask();
		getPrepayId.execute();
		
	}
	
	//生成支付参数
	public void genPayReq(){
		
		
		req = new PayReq();
		
		req.appId = Constants.APP_ID;
		req.partnerId = Constants.MCH_ID;
		req.prepayId = prepayId;
		req.packageValue = "Sign=WXPay";

		req.nonceStr = genNonceStr();
		req.timeStamp = String.valueOf(genTimeStamp());
				
		List<NameValuePair> signParams = new LinkedList<NameValuePair>();
		signParams.add(new BasicNameValuePair("appid", req.appId));
		signParams.add(new BasicNameValuePair("noncestr", req.nonceStr));
		signParams.add(new BasicNameValuePair("package", req.packageValue));
		signParams.add(new BasicNameValuePair("partnerid", req.partnerId));
		signParams.add(new BasicNameValuePair("prepayid", req.prepayId));
		signParams.add(new BasicNameValuePair("timestamp", req.timeStamp));

		req.sign = genAppSign(signParams);

		sb.append("sign\n"+req.sign+"\n\n");

		Log.e("orion", signParams.toString());
	}
	
	//发起支付请求 
	public void sendPayReq(){
		msgApi.sendReq(req);
	}
	
	private long genTimeStamp() {
		return System.currentTimeMillis() / 1000;
	}
	
	
	private String genAppSign(List<NameValuePair> params) {
		StringBuilder sb = new StringBuilder();

		for (int i = 0; i < params.size(); i++) {
			sb.append(params.get(i).getName());
			sb.append('=');
			sb.append(params.get(i).getValue());
			sb.append('&');
		}
		sb.append("key=");
		sb.append(Constants.API_KEY);

        this.sb.append("sign str\n"+sb.toString()+"\n\n");
		String appSign = MD5.getMessageDigest(sb.toString().getBytes()).toUpperCase();
		Log.e("orion",appSign);
		return appSign;
	}
	
	
	public static void sendCallBack(String result){
		if (instance == null) {
			return;
		}
		
		cordovaContext.success(result);
	}
	
	
	
	public void test(){
		
		Context Activity = this.cordova.getActivity().getApplicationContext();
		Toast.makeText(Activity, "hello,wechatpay", Toast.LENGTH_LONG).show();
	}
	
	public void toast(String text){
		Context Activity = this.cordova.getActivity().getApplicationContext();
		Toast.makeText(Activity, text, Toast.LENGTH_LONG).show();
	}

	
	private class GetPrepayIdTask extends AsyncTask<Void, Void, Map<String,String>> {

		private ProgressDialog dialog;

		@Override
		protected void onPreExecute() {
			//WechatPay.this.toast("请稍后...");
			//dialog = ProgressDialog.show(WechatPay.this.cordova.getActivity(), getString(R.string.app_tip), getString(R.string.getting_prepayid));
		}

		@Override
		protected void onPostExecute(Map<String,String> result) {
	
			if (dialog != null) {
				dialog.dismiss();
			}
			sb=new StringBuffer();
			sb.append("prepay_id\n"+result.get("prepay_id")+"\n\n");
			WechatPay.this.prepayId = result.get("prepay_id");
			//WechatPay.this.toast(sb.toString());
			WechatPay.this.genPayReq();
			WechatPay.this.sendPayReq();
			//resultunifiedorder=result;

		}

		@Override
		protected void onCancelled() {
			super.onCancelled();
		}

		@Override
		protected Map<String,String>  doInBackground(Void... params) {
			 
			String url = String.format("https://api.mch.weixin.qq.com/pay/unifiedorder");
			String entity = genProductArgs();
			
			Log.e("entity",entity);
			//没有连接网络时,获取不到数据，会导致APP终止
			byte[] buf = Util.httpPost(url, entity);
			String content = "";
			if(buf.length>0){
				content = new String(buf);
			}else{
				content = new String("");
			}
			Log.e("content", content);
			Map<String,String> xml=decodeXml(content);
			return xml;
		}
	}
	
	public Map<String,String> decodeXml(String content) {

		try {
			Map<String, String> xml = new HashMap<String, String>();
			XmlPullParser parser = Xml.newPullParser();
			parser.setInput(new StringReader(content));
			int event = parser.getEventType();
			while (event != XmlPullParser.END_DOCUMENT) {

				String nodeName=parser.getName();
				switch (event) {
					case XmlPullParser.START_DOCUMENT:

						break;
					case XmlPullParser.START_TAG:

						if("xml".equals(nodeName)==false){
							//实例化student对象
							xml.put(nodeName,parser.nextText());
						}
						break;
					case XmlPullParser.END_TAG:
						break;
				}
				event = parser.next();
			}

			return xml;
		} catch (Exception e) {
			Log.e("orion",e.toString());
		}
		return null;

	}
	
	private String genProductArgs() {
		StringBuffer xml = new StringBuffer();

		try {
			String	nonceStr = genNonceStr();

			JSONObject cfg = args.getJSONObject(0);
			
			Log.e("args",cfg.getString("body"));
						
			xml.append("</xml>");
            List<NameValuePair> packageParams = new LinkedList<NameValuePair>();
			packageParams.add(new BasicNameValuePair("appid", Constants.APP_ID));
			packageParams.add(new BasicNameValuePair("body", cfg.getString("body")));
			packageParams.add(new BasicNameValuePair("mch_id", Constants.MCH_ID));
			packageParams.add(new BasicNameValuePair("nonce_str", nonceStr));
			packageParams.add(new BasicNameValuePair("notify_url",cfg.getString("notify_url")));
			packageParams.add(new BasicNameValuePair("out_trade_no",cfg.getString("out_trade_no")));
			packageParams.add(new BasicNameValuePair("spbill_create_ip",cfg.getString("spbill_create_ip")));
			packageParams.add(new BasicNameValuePair("total_fee",cfg.getString("total_fee")));
			packageParams.add(new BasicNameValuePair("trade_type", "APP"));


			String sign = genPackageSign(packageParams);
			packageParams.add(new BasicNameValuePair("sign", sign));


		   String xmlstring =toXml(packageParams);
		   
           //改变拼接之后xml字符串格式
           return new String(xmlstring.toString().getBytes(), "ISO8859-1");

		} catch (Exception e) {
			Log.e(TAG, "genProductArgs fail, ex = " + e.getMessage());
			return null;
		}
		

	}
	
	
	private String toXml(List<NameValuePair> params) {
		StringBuilder sb = new StringBuilder();
		sb.append("<xml>");
		for (int i = 0; i < params.size(); i++) {
			sb.append("<"+params.get(i).getName()+">");


			sb.append(params.get(i).getValue());
			sb.append("</"+params.get(i).getName()+">");
		}
		sb.append("</xml>");

		Log.e("orion",sb.toString());
		return sb.toString();
	}
	
	/**
	 生成签名
	 */

	private String genPackageSign(List<NameValuePair> params) {
		StringBuilder sb = new StringBuilder();
		
		for (int i = 0; i < params.size(); i++) {
			sb.append(params.get(i).getName());
			sb.append('=');
			sb.append(params.get(i).getValue());
			sb.append('&');
		}
		sb.append("key=");
		sb.append(Constants.API_KEY);
		

		String packageSign = MD5.getMessageDigest(sb.toString().getBytes()).toUpperCase();
		Log.e("orion",packageSign);
		return packageSign;
	}
	
	private String genNonceStr() {
		Random random = new Random();
		return MD5.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes());
	}
	
	private String genOutTradNo() {
		Random random = new Random();
		return MD5.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes());
	}
}
